package com.xiyu.service.service.health;

import com.xiyu.service.enums.medicine.HealthMedicineStockRecordTypeEnum;
import com.xiyu.service.model.medicine.*;
import com.xiyu.service.repository.medicine.HealthMedicineStockRecordRepository;
import com.xiyu.service.repository.medicine.HealthMedicineStockRepository;
import com.xiyu.service.vo.health.medicineDeposit.MedicineDepositGetElderMedicineOutput;
import com.xiyu.service.vo.health.medicineDeposit.MedicineDepositCreateInput;
import com.xiyu.service.repository.medicine.HealthMedicineDepositRepository;
import com.xiyu.service.vo.health.medicineDeposit.MedicineDepositPageQueryOutput;
import com.xiyu.service.vo.health.medicineDeposit.MedicineDepositPageQueryInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.health.MedicineDepositConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.health.MedicineDepositErrorCode.*;

/**
 * 药品缴存 Service 实现类
 */
@Service
@Validated
public class MedicineDepositServiceImpl implements MedicineDepositService {

    @Resource
    private HealthMedicineDepositRepository healthMedicineDepositRepository;

    @Resource
    private HealthMedicineStockRepository healthMedicineStockRepository;

    @Resource
    private HealthMedicineStockRecordRepository healthMedicineStockRecordRepository;

    @Override
    public PageResult<MedicineDepositPageQueryOutput> pageQuery(MedicineDepositPageQueryInput inputVO) {
        Page<HealthMedicineDeposit> pageHealthMedicineDeposit = healthMedicineDepositRepository.pageQuery(inputVO);
        List<MedicineDepositPageQueryOutput> listHealthMedicineDeposit = MedicineDepositConvert.INSTANCE.pageQueryOutputConvert(pageHealthMedicineDeposit.getRows());
        return new PageResult<>(listHealthMedicineDeposit, pageHealthMedicineDeposit.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean create(List<MedicineDepositCreateInput> inputVO) {
        if(inputVO.isEmpty()){
            throw exception(HEALTH_MEDICINE_DEPOSIT_DETAIL_NOT_EMPTY);
        }
        List<HealthMedicineDeposit> newHealthMedicineDeposit = MedicineDepositConvert.INSTANCE.createInputConvert(inputVO);
        // 更新或创建药品库存
        for(HealthMedicineDeposit deposit : newHealthMedicineDeposit){
            Optional<HealthMedicineStock> optionalStock = healthMedicineStockRepository.findFirstByElderIdAndMedicineId(deposit.elderId(), deposit.medicineId());
            HealthMedicineStock stock;
            if(optionalStock.isPresent()){
                stock = HealthMedicineStockDraft.$.produce(optionalStock.get(), draft -> {
                    draft.setStockNumber(draft.stockNumber().add(deposit.number()));
                });
                healthMedicineStockRepository.update(stock);
            }else {
                stock = HealthMedicineStockDraft.$.produce(draft -> {
                    draft.setStockNumber(deposit.number()).setElderId(deposit.elderId()).setMedicineId(deposit.medicineId());
                });
                stock = healthMedicineStockRepository.insert(stock);
            }

            // 新建药品库存记录
            HealthMedicineStock finalStock = stock;
            HealthMedicineStockRecord stockRecord = HealthMedicineStockRecordDraft.$.produce(draft -> {
                draft.setStockId(finalStock.id()).setRecordType(HealthMedicineStockRecordTypeEnum.DEPOSIT.getValue())
                        .setNumber(deposit.number());
            });
            healthMedicineStockRecordRepository.insert(stockRecord);
        }

        // 创建药品缴存
        healthMedicineDepositRepository.saveAll(newHealthMedicineDeposit);
        return true;
    }

    @Override
    public List<MedicineDepositGetElderMedicineOutput> getElderMedicine(Long elderId) {
        return MedicineDepositConvert.INSTANCE.getElderMedicineOutputConvert(
                healthMedicineDepositRepository.findByElderId(elderId)
        );
    }

}
